/*
 * client_connectionless.c
 *
 *  Created on: 2012-5-2
 *      Author: jawinton
 */

#include "../apue.h"
#include <netdb.h>
#include <sys/socket.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define TIMEOUT 10
#define BUFLEN 128

void print_uptime (int sockfd, struct addrinfo *aip) {
	int n;
	char buf[BUFLEN];

	buf[0] = 0;
	if (sendto(sockfd, buf, 1, 0, aip->ai_addr, aip->ai_addrlen) < 0) err_sys("sendto error");
	alarm(TIMEOUT);
	if ((n = recvfrom(sockfd, buf, BUFLEN, 0, NULL, NULL)) < 0) {
		if (errno != EINTR) alarm(0);
		err_sys("recv error");
	}
	alarm(0);
	write(STDOUT_FILENO, buf, n);
}

int main (int argc, char *argv[]) {
	int sockfd, err;
	struct addrinfo *ailist, *aip;
	struct addrinfo hint;
	struct sockaddr_in *sinp;
	const char *addr;
	char abuf[INET_ADDRSTRLEN];
	struct sigaction sa;

	if (argc != 3) err_quit("usage: ruptime hostname service");
	sa.sa_handler = SIGALRM;
	sa.sa_flags = 0;
	sigemptyset(&sa.sa_mask);
	if (sigaction(SIGALRM, &sa, NULL) < 0) err_sys("sigaction error");
	hint.ai_addr = NULL;
	hint.ai_addrlen = 0;
	hint.ai_canonname = NULL;
	hint.ai_family = 0;
	hint.ai_flags = AI_CANONNAME;
	hint.ai_next = NULL;
	hint.ai_protocol = 0;
	hint.ai_socktype = SOCK_DGRAM;

	//getaddrinfo的第二个参数需要在/etc/services中存在对应的端口号和协议
	if ((err = getaddrinfo(argv[1], argv[2], &hint, &ailist)) != 0)
	//if ((err = getaddrinfo(argv[1], NULL, &hint, &ailist)) != 0)
		err_quit("getaddrinfo error: %s", gai_strerror(err));
	for (aip = ailist; aip != NULL; aip = ailist->ai_next) {
		if (aip->ai_family == AF_INET) {
			sinp = (struct sockaddr_in *)aip->ai_addr;
			addr = inet_ntop(aip->ai_family, &sinp->sin_addr, abuf, INET_ADDRSTRLEN);
			printf(" address %s (%s)", addr?addr:"unknown", aip->ai_canonname);
			printf(" port %d", ntohs(sinp->sin_port));
		}
		printf("\n");
		if ( (sockfd = socket(aip->ai_family, SOCK_DGRAM, 0)) < 0) err = errno;
		else {
			print_uptime(sockfd, aip);
			exit(0);
		}
	}
	fprintf(stderr, "cant't connect to %s: %s\n", argv[1], strerror(err));
	exit(1);
}
